home *** CD-ROM | disk | FTP | other *** search
- /* igscomm.c
- * S.Coffin USWAT 3/93
- *
- * Simple socket-based comm program for calling the igs
- */
-
- /* Copyright (c) 1992 by Stephen Coffin. All rights reserved.
- *
- * This program is distributed in the hope that it will be useful.
- * Use and copying of this software and preparation of derivative works
- * based upon this software are permitted, so long as the following
- * conditions are met:
- * o credit to the authors is acknowledged following current
- * academic behavior
- * o no fees or compensation are charged for use, copies, or
- * access to this software
- * o this copyright notice is included intact.
- * This software is made available AS IS, and no warranty is made about
- * the software or its performance.
- *
- * Bug descriptions, use reports, comments or suggestions are welcome.
- * Send them to scoffin@advtech.uswest.com
- */
-
- #include "igscomm.h"
-
- #define USAGE "Usage: %s [-d] [-?] [-e] [-h host-address] [-p port-number]\n"
-
- int dbg = FALSE;
- void SCbcopy();
- int port = PORT;
- int echoflag = TRUE;
-
- /* thanks to jpab+@andrew.cmu.edu for providing this function, improving
- * DNS lookups of numeric or logical internet addresses =SC
- */
- long io_lookup_addr( str )
- unsigned char *str;
- {
- u_long addr;
- struct hostent *hp;
-
- if( isdigit(str[0]) ) {
- return inet_addr( str );
- }
- else {
- if( (hp = gethostbyname(str)) == NULL ) {
- fprintf( stderr, "can't find the address of '%s'\n", str );
- exit( 1 );
- }
- SCbcopy( hp->h_addr_list[0], &addr, sizeof(struct in_addr) );
- return addr;
- }
- }
-
- main( argc, argv )
- int argc;
- char *argv[];
- {
- int i, j, sd, count, ret;
- unsigned char *r;
- char *host = HOST;
- struct sockaddr_in sin;
- unsigned char str[MSG_SIZE+1];
- fd_set xx;
- struct timeval timeout;
- int yy = 32;
- extern int getopt();
- extern char *optarg;
- extern int optind;
- int c, skipcount = 0;
- #ifdef BSD
- struct sgttyb tin, tout;
- #else
- struct termio tin, tout;
- #endif
-
- while( (c=getopt( argc, argv, "?h:p:de" )) != (-1) ) {
- switch( c ) {
- case 'd': /* debug mode */
- dbg = TRUE;
- break;
- case 'e': /* disable echo */
- echoflag = FALSE;
- break;
- case 'p': /* socket number */
- port = atoi( optarg );
- break;
- case 'h': /* host id */
- host = optarg;
- break;
- case '?':
- default:
- fprintf( stderr, "%s: Release %s\n", argv[0], PATCHLEVEL );
- fprintf( stderr, USAGE, argv[0] );
- exit( (-1) );
- break;
- }
- }
-
- if( optind != argc ) {
- fprintf( stderr, "%s: Release %s\n", argv[0], PATCHLEVEL );
- fprintf( stderr, USAGE, argv[0] );
- exit( (-1) );
- }
-
- sin.sin_addr.s_addr = io_lookup_addr( host );
- sin.sin_family = AF_INET;
- sin.sin_port = htons( port );
-
- if( (sd=socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) {
- perror( "socket" );
- exit( 2 );
- }
-
- if( connect( sd, (unsigned char *)&sin, sizeof( sin ) ) < 0 ) {
- perror( "connect" );
- exit( 3 );
- }
-
- /* connected now */
-
- /* turn off echo */
- /*XXX I don't know if this code is ok for ALL UNIX versions */
- if( !echoflag ) {
- #ifdef BSD
- ioctl( fileno(stdin), TIOCGETP, &tin );
- tout = tin;
- tout.sg_flags &= ~ECHO;
- ioctl( fileno(stdin), TIOCSETP, &tout );
- #else
- ioctl( fileno(stdin), TCGETA, &tin );
- tout = tin;
- tout.c_lflag &= ~ECHO;
- ioctl( fileno(stdin), TCSETAW, &tout );
- #endif
- }
-
- for( ;; ) {
- timeout.tv_sec = TIMEOUT;
- timeout.tv_usec = 0L;
- FD_ZERO( &xx );
- FD_SET( sd, &xx ); /* listen on the socket */
- FD_SET( 0, &xx ); /* listen for kbd input */
-
- ret = select( yy, &xx, NULL, NULL, &timeout );
-
- /* error ? */
- if( ret < 0 ) {
- /* exit on interrupt ?? */
- if( errno == EINTR ) break;
-
- /* any other interruption is an error! */
- else {
- perror( "select" );
- break;
- }
- }
-
- /* timeout */
- else if( ret == 0 ) {
- if( dbg ) fprintf( stderr, "Timeout\n" );
- continue;
- }
-
- /* input from socket.... print it */
- else if( FD_ISSET( sd, &xx ) ) {
- FD_CLR( sd, &xx );
- if( (count=recv( sd, str, MSG_SIZE, 0 )) < 0 ) {
- perror( "recv" );
- break;
- }
- if( count == 0 ) {
- fprintf( stderr, "Connection closed by foreign host.\n" );
- break;
- }
-
- str[count] = '\0';
- for( j=0; j < count; ++j ) {
-
- /* igonore 3-char sequences beginning with 0xff */
- if( str[j] == 0xff ) {
- skipcount = 2;
- }
-
- /* answer "are you there" request from server */
- else if( skipcount == 2 && str[j] == 0xf6 ) {
- skipcount = 0;
- sprintf( (char *)str, "\r\n" );
- if( send( sd, str, 2, 0 ) ) {
- perror( "send" );
- break;
- }
- }
- else if( skipcount > 0 ) {
- --skipcount;
- }
- else putchar( str[j] );
- }
- fflush( stdout );
- continue;
- }
-
- /* input from keyboard.... send it */
- else if( FD_ISSET( 0, &xx ) ) {
- FD_CLR( 0, &xx );
- if( (r = (unsigned char *)gets( (char *)str )) == NULL ) break;
- j = strlen( (char *)str );
- if( str[0] == '.' && j == 1 ) break;
- str[j++] = '\r';
- str[j++] = '\n';
- str[j+1] = '\0';
-
- /* send a message to the server PORT on HOST */
- if( send( sd, str, j, 0 ) < 0 ) {
- perror( "send" );
- break;
- }
- continue;
- }
- }
-
- /* close the socket connection */
- if( shutdown( sd, 2 ) < 0 ) {
- perror( "shutdown" );
- exit( 1 );
- }
-
- close( sd );
- }
-
- /* really crude, unsafe version of bcopy() */
- void SCbcopy( b1, b2, length )
- register unsigned char *b1;
- register unsigned char *b2;
- register unsigned length;
- {
- while( length-- > 0 ) *b2++ = *b1++;
- }
-